/*
 * Copyright (C) 2022-2024 Huawei Device Co., Ltd.
 * Licensed under the MIT License, (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://opensource.org/licenses/MIT
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

import type { PubSubSupport } from '../interface/PubSubSupport'
import { SubscriptionManager } from '../subscription/SubscriptionManager'
import { BusRuntime } from './BusRuntime'
import type { IMessagePublication } from './IMessagePublication'
import type { IBusConfiguration } from '../config/IBusConfiguration'
import { SyncPubSub } from '../config/SyncPubSub'
import { MessagePublicationFactory } from './MessagePublication'
import { Subscription } from '../subscription/Subscription'
import ArrayList from '@ohos.util.ArrayList';


export abstract class AbstractPubSubSupport<T> implements PubSubSupport<T> {
    private subscriptionManager: SubscriptionManager;
    private runtime: BusRuntime;
    private publicationFactory: MessagePublicationFactory;

    constructor(config: IBusConfiguration) {
        this.runtime = new BusRuntime(this);
        let pubSubFeature = config.getFeature('SyncPubSub');
        if (!pubSubFeature) {
            throw new Error('missing Feature');
        }

        let syncFeature = pubSubFeature as SyncPubSub;
        this.subscriptionManager = syncFeature.getSubscriptionManagerProvider()
            .createManager(
            syncFeature.getMetadataReader(),
            syncFeature.getSubscriptionFactory(),
            this.runtime
            );
        this.publicationFactory = syncFeature.getPublicationFactory();
    }

    subscribe(listener: Object): void {
        if (this.subscriptionManager) {
            this.subscriptionManager.subscribe(listener);
        }
    }

    unSubscribe(listener: Object): boolean {
        if (this.subscriptionManager) {
            return this.subscriptionManager.unsubscribe(listener);
        }
        return false;
    }

    getSubscriptionManager(): SubscriptionManager {
        return this.subscriptionManager;
    }

    publish(message: T) {
        // TODO
    }

    getRunTime(): BusRuntime {
        return this.runtime;
    }

    publishAsyncStart(message: T, pub: IMessagePublication) {
        new Promise<string>((resolve, reject) => {
            try {
                pub.executeAsyn();
                resolve('success');
            } catch (error) {
                reject(error);
            }
        }).then((v) => {
            console.log(v.toString())
        }).catch((err) => {
            console.log(err);
        })
    }

    createMessagePublication(message: T): IMessagePublication {
        let subManager: SubscriptionManager = this.getSubscriptionManager();
        let array: Array<Subscription> = subManager.getSubscriptionsByClassName();
        if (!array) {
            throw new Error('no found Subscription of class name');
        }
        let arrayListSun = new ArrayList<Subscription>();
        array.forEach((value, index) => {
            arrayListSun.add(value);
        })
        arrayListSun.sort((first: Subscription, second: Subscription) => second.getPriority() - first.getPriority());
        var messagePublication = this.publicationFactory.createPublication(this.runtime, arrayListSun, message);
        return messagePublication;
    }
}